/*
 * 状态模式 State Pattern
 *
 * author: 徐冉辰 2021080908028
 */
#pragma once

#include <fstream>
#include <iostream>
#include <string>
#include <map>
#include <cctype>
#include <algorithm>
#include <exception>

#include "../TokenTable.h"

// const std::set<char> punctuation = {'=', '<', '>', '-', '*', ':', '(', ')', ';'};
// bool isOperators(char c);

enum StateType
{
	ACCEPT,					   /* 接收字符 */
	ERROR_ILLEGALCHAR,		   /* 非法字符 */
	ERROR_COLON_MATCH,		   /* 冒号不匹配 */
	ERROR_IDENTIFIER_OVERFLOW, /* 标识符长度溢出 */
	ERROR_CONSTANT_OVERFLOW,   /* 常量长度溢出 */
	END_LINE,				   /* 行结束 */
	END_FILE,				   /* 文件结束 */
	OTHER
};

/*
 * Token 每次文本分析获取的词法单位
 * - 用于数据传递
 */
class Token
{
public:
	std::string value;
	int type;
	StateType state;
	std::string info;

	Token(StateType state = OTHER) : state(state) {}
	void resetToken();
};

enum TokenStateType
{
	KEYWORD,
	OPERATOR,
	CONSTANT,
	OTHER_PUNCTUATION
};

/*
 * TokenState 抽象基类
 */
class TokenState
{
public:
	Token token;

	virtual ~TokenState() {}
	virtual Token getToken(std::string::const_iterator char_ptr) = 0;
};

/*
 * 识别关键字KEYWORD & 标识符IDENTIFIER
 * begin 1  end 2  integer 3  if 4  then 5  else 6  function 7  read 8  write 9
 */
class KeywordState : public TokenState
{
private:
	std::map<std::string, int> TokenTable = {
		{"begin", 1},
		{"end", 2},
		{"integer", 3},
		{"if", 4},
		{"then", 5},
		{"else", 6},
		{"function", 7},
		{"read", 8},
		{"write", 9}};

public:
	Token getToken(std::string::const_iterator char_ptr) override;
};

/*
 * 识别操作符OPERATOR
 * = 12  <> 13  <= 14  < 15  >= 16  > 17  - 18  * 19  := 20  ( 21  ) 22  ; 23
 */
class OperatorState : public TokenState
{
private:
	std::map<std::string, int> TokenTable = {
		{"=", 12},
		{"<>", 13},
		{"<=", 14},
		{"<", 15},
		{">=", 16},
		{">", 17},
		{"-", 18},
		{"*", 19},
		{":=", 20},
		{"(", 21},
		{")", 22},
		{";", 23}};

public:
	Token getToken(std::string::const_iterator char_ptr) override;
};

/*
 * 识别常量CONSTANT
 */
class ConstantState : public TokenState
{
public:
	Token getToken(std::string::const_iterator char_ptr) override;
};

/*
 * 识别非法输入符号
 * - 在 '=', '<', '>', '-', '*', ':', '(', ')', ';' 之外的符号
 */
class OtherPunctuationState : public TokenState
{
public:
	Token getToken(std::string::const_iterator char_ptr) override;
};

/*
 * 控制状态切换
 */
class Tokenizer
{
private:
	TokenState *currentState;
	std::map<TokenStateType, TokenState *> TokenStateList;

public:
	Tokenizer();
	~Tokenizer();

	Token getNextToken(std::string::const_iterator char_ptr);
};